home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / standards / sgml / nist / parse1 / dtd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-13  |  18.1 KB  |  622 lines

  1. /* National Institute of Standards and Technology (NIST)
  2. /* National Computer System Laboratory (NCSL)
  3. /* Office Systems Engineering (OSE) Group
  4. /* ********************************************************************
  5. /*                            D I S C L A I M E R
  6. /*                              (March 8, 1989)
  7. /*  
  8. /* There is no warranty for the NIST NCSL OSE SGML parser and/or the NIST
  9. /* NCSL OSE SGML parser validation suite.  If the SGML parser and/or
  10. /* validation suite is modified by someone else and passed on, NIST wants
  11. /* the parser's recipients to know that what they have is not what NIST
  12. /* distributed, so that any problems introduced by others will not
  13. /* reflect on our reputation.
  14. /* 
  15. /* Policies
  16. /* 
  17. /* 1. Anyone may copy and distribute verbatim copies of the SGML source
  18. /* code as received in any medium.
  19. /* 
  20. /* 2. Anyone may modify your copy or copies of SGML parser source code or
  21. /* any portion of it, and copy and distribute such modifications provided
  22. /* that all modifications are clearly associated with the entity that
  23. /* performs the modifications.
  24. /* 
  25. /* NO WARRANTY
  26. /* ===========
  27. /* 
  28. /* NIST PROVIDES ABSOLUTELY NO WARRANTY.  THE SGML PARSER AND VALIDATION
  29. /* SUITE ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
  30. /* EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  31. /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  32. /* THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS
  33. /* WITH YOU.  SHOULD THE SGML PARSER OR VALIDATION SUITE PROVE DEFECTIVE,
  34. /* YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  35. /* 
  36. /* IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL NIST BE LIABLE FOR
  37. /* DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
  38. /* INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
  39. /* INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
  40. /* BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
  41. /* FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
  42. /* NIST) THE PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF
  43. /* SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
  44. */
  45.  
  46. /************************************************************************/
  47. /*   TITLE:          SGML PARSER                                        */
  48. /*   SYSTEM:         DTD PROCESSOR                                      */
  49. /*   SUBSYSTEM:                                                         */
  50. /*   SOURCE FILE:    DTD.C                                              */
  51. /*   AUTHOR:         Jim Heath                                          */
  52. /*                                                                      */
  53. /*   DATE CREATED:                                                      */
  54. /*   LAST MODIFIED:                                                     */
  55. /*                                                                      */
  56. /*                  REVISIONS                                           */
  57. /*   WHEN      WHO            WHY                                       */
  58. /************************************************************************/
  59. #include <stdio.h>
  60. #include <setjmp.h>
  61. #include <unistd.h>
  62.  
  63. #include "qntyset.h"
  64. #include "dtd.h"
  65. #include "dtdfncs.h"
  66. #include "dtdglbl.h"
  67. #include "dtddefs.h"
  68.  
  69. #define      MAXDECLSIZE           2048
  70. static char decl[MAXDECLSIZE];
  71. #define  DEMO   0
  72. int num_open_ms=0;
  73.  
  74. /* ============================================================ */
  75. main(argc, argv)
  76. int argc;
  77. char *argv[];
  78. {
  79. #undef PROFILE
  80.    char *targv[2];
  81.    REGISTER int j;
  82.    filemask = 0;
  83.    FUNCTRACE("main");
  84. #ifdef PROFILE
  85.    argc = 2;
  86.    targv[0] = "parse1";
  87.    targv[1] = "testdoc";
  88.    doopts(argc, targv);
  89.    dofiles(targv);
  90. #else 
  91.    doopts(argc, argv);
  92.    dofiles(argv);
  93. #endif
  94. SETENV:
  95.    if (setjmp(Xenv) != 0) {
  96.       while(1) {
  97.          if ((j = jgetc()) == EOF)
  98.             terminate(1, "EOF while recovering for syntax error");
  99.          if (j == MDC) {
  100.             stackinit();
  101.             goto SETENV;
  102.          }
  103.       }
  104.    }
  105.    processinput();
  106. }
  107. /* ============================================================ */
  108. void processinput()
  109. {
  110.    int tempnum, elements = 0, attributes = 0, 
  111.    entities = 0;
  112.    enum    {
  113.       TRYPIO, GETDS, GETMDO, GETKEYWORD, TRYSGML                                                                  }
  114.    state = TRYSGML;
  115.  
  116.    do {
  117.       switch(state) {
  118.       case TRYSGML:
  119.          dogetsgml();     /* look for and strip sgml declaration */
  120.          state = GETDS;
  121.          break;
  122.       case GETDS:
  123.          tempnum = num_open_ms;
  124.          CLEARFLAG(IN_DECL);
  125.          dogetds(elements, attributes, entities);  /* arguments are for show count */
  126.          if (num_open_ms > 0)
  127.             get_ms_closes();
  128.          if (tempnum == num_open_ms)
  129.             state = GETMDO;
  130.          else 
  131.             state = GETDS;
  132.          break;
  133.       case TRYPIO:
  134.          dopio();
  135.          state = GETDS;
  136.          break;
  137.       case GETMDO:
  138.          CLRDECL();
  139.          SETFLAG(IN_DECL);
  140.          if (TESTFLAG(IN_ENTITY))
  141.             SETFLAG(DECL_IS_IN_ENTITY);
  142.          else
  143.             CLEARFLAG(DECL_IS_IN_ENTITY);
  144.          if ((inpMDO()) != GOOD)
  145.             state = TRYPIO;
  146.          else
  147.             state = GETKEYWORD;
  148.          break;
  149.       case GETKEYWORD:
  150.          dokeyword();
  151.          state = GETDS;
  152.       }
  153.    }     while(1);
  154. }
  155. /* ============================================================ */
  156. /* ============================================================ */
  157. void doopts(argc, argv)
  158. int argc;
  159. char *argv[];
  160. {
  161.    REGISTER int j;
  162.    FUNCTRACE("doopts");
  163.    printf("argc = %d\n", argc);
  164.    for (j = 0; j < argc; j++)
  165.       printf("argv[%d] = %s\n", j, argv[j]);
  166.    for (j = 2; j < argc; j++) {
  167.       switch(*(argv[j] + 1)) {
  168.       case 'P':
  169.       case 'p':
  170.          strcpy(entfilename, (argv[j] + 2));
  171.          break;
  172.       case 'T':
  173.       case 't':
  174.          strcpy(pathname, (argv[j] + 2));
  175.          if (*(pathname + strlen(pathname) -1) == ':')
  176.             strcat(pathname, "\\");
  177.          else if (ISALPHA(*(pathname + strlen(pathname) -1)))
  178.             strcat(pathname, ":\\");
  179.          break;
  180.       case '1':
  181.          debug = atoi((argv[j] + 2));
  182.          break;
  183.       case 'F':
  184.          deletefiles = FALSE;
  185.          break;
  186.       case 'H':
  187.          /*         heading();*/
  188.          break;
  189.       default:
  190.          terminate(1, "illegal option to PARSE1");
  191.       }
  192.    }
  193. }
  194. /* ============================================================ */
  195. void dofiles(argv)
  196. char *argv[];
  197. {
  198.    /* create the intermediate work files */
  199.    FUNCTRACE("dofiles");
  200.    strcpy(treefname,pathname);
  201.    strcat(treefname,"treefile.sgm");
  202.  
  203.    strcpy(symbfname,pathname);
  204.    strcat(symbfname,"symbfile.sgm");
  205.  
  206.    /* create the attribute file */
  207.    strcpy(attrfname,pathname);
  208.    strcat(attrfname,"attrfile.sgm");
  209.  
  210.    /* create the attribute work file */
  211.    strcpy(attrtname,pathname);
  212.    strcat(attrtname,"attrtemp.sgm");
  213.  
  214.    /* build the dtdfile for later use */
  215.    strcpy(dtdfname,pathname);
  216.    strcat(dtdfname,"dtdfile1.sgm");
  217.  
  218.    strcpy(preffname,pathname);
  219.    strcat(preffname,"preffile.sgm");
  220.  
  221.    strcpy(greffname,pathname);
  222.    strcat(greffname,"greffile.sgm");
  223.  
  224.    strcpy(posfname,pathname);
  225.    strcat(posfname,"posfile.sgm");
  226.  
  227.    strcpy(xcptfname,pathname);
  228.    strcat(xcptfname,"except.sgm");
  229.  
  230.    strcpy(exclfname,pathname);
  231.    strcat(exclfname,"exclusns.sgm");
  232.  
  233.    strcpy(inclfname,pathname);
  234.    strcat(inclfname,"inclusns.sgm");
  235.  
  236.    strcpy(cmfname,pathname);
  237.    strcat(cmfname,"cmfile.sgm");
  238.  
  239.    /* build the name for my input file */
  240.    strcpy(docfname, argv[1]);
  241.  
  242.    unlinkall(TRUE);
  243.  
  244.    treefile = safecreat(treefname, TREEFILE);
  245.    symbfile = safecreat(symbfname, SYMBFILE);
  246.    attrtemp = safecreat(attrtname, ATTRTEMP);
  247.    preffile = safecreat(preffname, PREFFILE);
  248.    greffile = safecreat(greffname, GREFFILE);
  249.    docfile = safefopen(docfname, "r", DOCFILE);
  250.    cmfile = safefopen(cmfname, "wb", CMFILE);
  251.    inclfile = safecreat(inclfname, INCLFILE);
  252.    exclfile = safecreat(exclfname, EXCLFILE);
  253. }
  254. /* ============================================================ */
  255. void dodecl(clrflag, c, inptr, outptr)
  256. int clrflag;
  257. char c;
  258. REGISTER char *inptr;
  259. char **outptr;
  260. {
  261.    static char *declptr = decl;
  262.  
  263.  
  264.    if(clrflag == ON){
  265.       memset(decl, '\0', MAXDECLSIZE);
  266.       declptr = decl;
  267.       return;
  268.    }
  269.    if(c != NULL){
  270.       if(declptr != (decl + MAXDECLSIZE)){
  271.          *declptr++ = c;
  272.          *declptr = '\0';
  273.          return;
  274.       }
  275.       else
  276.          terminate(1, "MAXDECLSIZE exceeded in normalized declaration buffer");
  277.    }
  278.    if(inptr != NULL){
  279.       while(*inptr != '\0'){
  280.          if(declptr == (decl + MAXDECLSIZE))
  281.             terminate(1, "MAXDECLSIZE exceeded in normalized declaration buffer");
  282.          *declptr++ = *inptr++;
  283.          *declptr = '\0';
  284.       }
  285.       return;
  286.    }
  287.    if(outptr != NULL){
  288.       *outptr = decl;
  289.       return;
  290.    }
  291. }
  292. /* ============================================================ */
  293. void writeposition()
  294. {
  295.    long position;
  296.    int  posfile;
  297.    position = ftell(docfile);
  298.    if (position == -1L)
  299.       terminate(1, "failure on lseek");
  300.    posfile = safecreat(posfname, POSFILE);
  301.    safewrite(posfile, (char *) &position, sizeof(position));
  302.    safeclose(posfile, "position file", POSFILE);
  303. }
  304. /* ============================================================ */
  305. static void showcounts(elements, attributes, entities)
  306. int elements, attributes, entities;
  307. {
  308.    printf("\ntotal elements = %d\n", elements);
  309.    printf("total attributes = %d\n", attributes);
  310.    printf("total entities = %d\n\n", entities);
  311. }
  312. /* ============================================================ */
  313. void dogetds(elements, attributes, entities)
  314. int elements, attributes, entities;
  315. {
  316.    REGISTER int j;
  317.    if (INPDS() == EOF)   /* inpsep: gets s's */
  318.       terminate(1, "EOF found while looking for DS");
  319.    if ((j = jgetc()) != DSC) {
  320.       jungetc(j);
  321.       return;
  322.    }
  323.    ADDCHAR(DSC);
  324.    if (INPPS() == EOF)
  325.       terminate(1, "EOF found following DSC");
  326.    if ((j = jgetc()) == MDC) {
  327.       finddocelt();
  328.       writeposition();
  329.       ADDCHAR(DSC);
  330.       closeall();
  331.       showcounts(elements, attributes, entities);
  332.       if (strlen(rootelt) != 0) {
  333.          printf("\n\nERROR - no element declaration for root element\n");
  334.          errflag = 1;
  335.       }
  336.       if (errflag == 0)
  337.          bldsymbtbl();
  338.       else {
  339.          unlinkall(TRUE);
  340.          exit(1);
  341.       }
  342.    }
  343.    else 
  344.       if (j == DSC) {
  345.          jungetc(']');
  346.          jungetc(']');
  347.       }
  348.       else
  349.          terminate(1, "expected MDC following DSC");
  350. }
  351. /* ============================================================ */
  352. void dopio()
  353. {
  354.    REGISTER int j, count = 0;
  355.    char *mydecl;
  356.    if ((j = jgetc()) == EOF)
  357.       terminate(1, "EOF found");
  358.    if (j == '<') {
  359.       ADDCHAR(j);
  360.       if ((j = jgetc()) == EOF)
  361.          terminate(1, "EOF within declaration");  /* not really a valid statement */
  362.       ADDCHAR(j);
  363.       if (j != '?')
  364.          syntxerr("expected MDO or PIO");
  365.    }
  366.    else 
  367.       syntxerr("expected MDO or PIO");
  368.    do {    /* found valid PIO */
  369.       if (count > PILEN)
  370.          syntxerr("length of processing instruction exceeds PILEN");
  371.       if ((j = jgetc()) == EOF)
  372.          terminate(1, "EOF within declaration");
  373.       ++count;
  374.       ADDCHAR(j);
  375.    }   while(j != MDC);
  376.    GETDECLADDR(&mydecl);
  377.    printf("%s\n", mydecl);
  378. }
  379. /* ============================================================ */
  380. void finddocelt()
  381. {
  382.    long currpos;
  383.    int c;
  384.  
  385. STEP1:
  386.    while(1) {
  387.       CLRDECL();
  388.       while(1) {
  389.          if ((c = getc(docfile)) == EOF)
  390.             PERROR("unexpected EOF in finddocelt");
  391.          switch(c) {
  392.          case ERO:
  393.             if ((currpos = ftell(docfile)) == -1L)
  394.                PERROR("failure in ftell(docfile) in finddocelt");
  395.             currpos--;
  396.             if ((c = getc(docfile)) == EOF)
  397.                PERROR("unexpected EOF in finddocelt");
  398.             if (isnmstrt(c))  {
  399.                ADDCHAR(ERO);
  400.                ADDCHAR(c);
  401.                syntxerr("illegal character found while searching other prolog");
  402.             }
  403.             if (fseek(docfile, currpos, SEEK_SET) == -1L)
  404.                PERROR("failure in fseek(docfile) in finddocelt()");
  405.             return;
  406.          case SPACE:
  407.          case RS:
  408.          case RE:
  409.          case TAB:
  410.             continue;
  411.          case '<':
  412.             finddocelt2();
  413.             return;
  414.          default:
  415.             if ((currpos = ftell(docfile)) == -1L)
  416.                PERROR("failure in ftell(docfile) in finddocelt");
  417.             currpos--;
  418.             if (fseek(docfile, currpos, SEEK_SET) == -1L)
  419.                PERROR("failure in fseek(docfile) in finddocelt()");
  420.             return;
  421.          }
  422.       }
  423.    }
  424. }
  425. /* ============================================================ */
  426. void finddocelt2()
  427. {
  428.    long currpos;
  429.    int c;
  430.    char *tdecl;
  431.  
  432.    if ((currpos = ftell(docfile)) == -1L)
  433.       PERROR("failure in ftell(docfile) in finddocelt2");
  434.    currpos--;
  435.    if ((c = getc(docfile)) == EOF)
  436.       PERROR("unexpected EOF in finddocelt2");
  437.    switch(c) {
  438.    case '?':
  439.       dopio2();
  440.       GETDECLADDR(&tdecl);
  441.       printf("%s\n", tdecl);
  442.       break;
  443.    case '!':
  444.       if (docomment() == FALSE){
  445.          if (fseek(docfile, currpos, SEEK_SET) == -1L)
  446.             PERROR("failure in fseek(docfile) in finddocelt2()");
  447.       }
  448.       GETDECLADDR(&tdecl);
  449.       printf("%s\n", tdecl);
  450.       break;
  451.    default:
  452.       if (fseek(docfile, currpos, SEEK_SET) == -1L)
  453.          PERROR("failure in fseek(docfile) in gotodocelt2()");
  454.    }
  455. }
  456. /* ============================================================ */
  457. void dopio2()
  458. {
  459.    int c;
  460.    int len = 0;
  461.  
  462.    ADDSTRING("<?");
  463.    while(1) {
  464.       if ((c = getc(docfile)) == EOF)
  465.          PERROR("unexpected EOF while reading other prolog");
  466.       ADDCHAR(c);
  467.       if (c == MDC)
  468.          return;
  469.       if (++len > PILEN)
  470.          syntxerr("PI too long in other prolog");
  471.    }
  472. }
  473. /* ============================================================ */
  474. int docomment()
  475. {
  476.    int c;
  477.    enum {
  478.       sawNONE, sawONE, sawTWO                      }
  479.    state;
  480.  
  481.    if ((c = getc(docfile)) == EOF)
  482.       PERROR("unexpected EOF while reading other prolog");
  483.    if (c != '-')
  484.       return(FALSE);
  485.    if ((c = getc(docfile)) == EOF)
  486.       PERROR("unexpected EOF while reading other prolog");
  487.    if (c != '-')
  488.       return(FALSE);
  489.    ADDSTRING("<!--");
  490. INSIDE_COMMENT:
  491.    for(state = sawNONE; state != sawTWO;) {
  492.       if ((c = getc(docfile)) == EOF)
  493.          PERROR("unexpected EOF while reading other prolog");
  494.       ADDCHAR(c);
  495.       if (c == '-') {
  496.          if (state == sawNONE)
  497.             state = sawONE;
  498.          else if (state == sawONE)
  499.             state = sawTWO;
  500.       }
  501.       else 
  502.          state = sawNONE;
  503.    }
  504.    while(1) {
  505.       if ((c = getc(docfile)) == EOF)
  506.          PERROR("unexpected EOF while reading other prolog");
  507.       ADDCHAR(c);
  508.       switch(c) {
  509.       case MDC:
  510.          return(TRUE);
  511.       case SPACE:
  512.       case RE:
  513.       case RS:
  514.       case TAB:
  515.          continue;
  516.       case '-':
  517.          if ((c = getc(docfile)) == EOF)
  518.             PERROR("unexpected EOF while reading other prolog");
  519.          ADDCHAR(c);
  520.          if (c == '-')
  521.             goto INSIDE_COMMENT;
  522.          syntxerr("illegal declaration in other prolog");
  523.       }
  524.    }
  525. }
  526. /* ============================================================ */
  527. void dokeyword()
  528. {
  529.    char namearray[NAMELEN + 1], *ptr, *mydecl;
  530.    int j, elements = 0, attributes = 0, 
  531.    entities = 0, notations = 0;
  532.    static int founddoctype = FALSE;
  533.  
  534.    ptr = namearray;
  535.    j = INPNAME( &ptr, NAMELEN, TOUPPER);
  536.    switch (j) {
  537.    case KW_DOCTYPE:
  538.       ADDSTRING("DOCTYPE");
  539.       if (INPPS() >= 1)
  540.          ADDCHAR(SPACE);
  541.       else
  542.          terminate(1, "Error while processing DOCTYPE declaration");
  543.       /* input the document name */
  544.       ptr = rootelt;
  545.       if (INPNAME( &ptr, NAMELEN, TOUPPER) >= GOOD){
  546.          ADDSTRING(rootelt);
  547.          INPPS();
  548.          if ((j = jgetc()) != DSO)
  549.             terminate(1, "Error while processing DOCTYPE declaration");
  550.          ADDSTRING(" [");
  551.       }
  552.       else 
  553.          terminate(1, "invalid docname");
  554.       founddoctype = TRUE;
  555.       break;
  556.    case KW_ENTITY:
  557.       ADDSTRING("ENTITY");
  558.       if(founddoctype == FALSE)
  559.          syntxerr("Entity declaration found before DOCTYPE declaration");
  560.       doentity();
  561.       entities++;
  562.       if (TESTFLAG(IN_ENTITY) != TESTFLAG(DECL_IS_IN_ENTITY))
  563.          syntxerr("illegal parameter entity reference");
  564.       break;
  565.    case KW_ELEMENT:
  566.       ADDSTRING("ELEMENT");
  567.       if(founddoctype == FALSE)
  568.          syntxerr("ELEMENT declaration found before DOCTYPE declaration");
  569.       elements += doelement();
  570.       if (TESTFLAG(IN_ENTITY) != TESTFLAG(DECL_IS_IN_ENTITY))
  571.          syntxerr("illegal parameter entity reference");
  572.       break;
  573.    case KW_ATTLIST:
  574.       ADDSTRING("ATTLIST");
  575.       if(founddoctype == FALSE)
  576.          syntxerr("ATTLIST declaration found before DOCTYPE declaration");
  577.       attributes += doattlist();
  578.       if (TESTFLAG(IN_ENTITY) != TESTFLAG(DECL_IS_IN_ENTITY))
  579.          syntxerr("illegal parameter entity reference");
  580.       break;
  581.    case KW_NOTATION:
  582.       ADDSTRING("NOTATION");
  583.       if(founddoctype == FALSE)
  584.          syntxerr("NOTATION declaration found before DOCTYPE declaration");
  585.       notations = donotation();
  586.       if (TESTFLAG(IN_ENTITY) != TESTFLAG(DECL_IS_IN_ENTITY))
  587.          syntxerr("illegal parameter entity reference");
  588.       break;
  589.    default:
  590.       j = jgetc();
  591.       if(j == MDC) {
  592.          if (TESTFLAG(IN_ENTITY) != TESTFLAG(DECL_IS_IN_ENTITY))
  593.             syntxerr("illegal parameter entity reference");
  594.          ADDCHAR(MDC);
  595.          break;       /* start over; look for another decl */
  596.       }
  597.       else if(j == '-') {
  598.          jungetc(j);
  599.          j = INPPS();    /* check for comment */
  600.          if ((j = jgetc()) != MDC) {
  601.             ADDCHAR(j);
  602.             syntxerr("illegal sequence following MDO");
  603.          }
  604.          if (TESTFLAG(IN_ENTITY) != TESTFLAG(DECL_IS_IN_ENTITY))
  605.             syntxerr("illegal parameter entity reference");
  606.          ADDCHAR(MDC);
  607.          break;
  608.       }
  609.       else if (j == DSO) {    /* check for marked section */
  610.          ADDCHAR(j);    /* add DSO to output */
  611.          get_marked_section();   /* process marked section */
  612.          break;
  613.       }
  614.       else {
  615.          ADDCHAR(j);
  616.          syntxerr("illegal sequence following MDO");
  617.       }
  618.    }
  619.    GETDECLADDR(&mydecl);
  620.    printf("%s\n", mydecl);
  621. }
  622.